home *** CD-ROM | disk | FTP | other *** search
Text File | 1995-03-27 | 20.7 KB | 481 lines | [TEXT/ROSA] |
- Common Lisp the Language, 2nd Edition
- -------------------------------------------------------------------------------
-
- 10. Symbols
-
- A Lisp symbol is a data object that has three user-visible components:
-
- * The property list is a list that effectively provides each symbol with
- many modifiable named components.
-
- * The print name must be a string, which is the sequence of characters used
- to identify the symbol. Symbols are of great use because a symbol can be
- located once its name is given (typed, say, on a keyboard). One may
- ordinarily not alter a symbol's print name.
-
- [change_begin]
- X3J13 voted in March 1989 (CHARACTER-PROPOSAL) to specify it is an error to
- alter a print name.
- [change_end]
-
- * The package cell must refer to a package object. A package is a data
- structure used to locate a symbol once given the symbol's name. A symbol
- is uniquely identified by its name only when considered relative to a
- package. A symbol may appear in many packages, but it can be owned by at
- most one package. The package cell points to the owner, if any. Package
- cells are discussed along with packages in chapter 11.
-
- A symbol may actually have other components for use by the implementation. One
- of the more important uses of symbols is as names for program variables; it is
- frequently desirable for the implementor to use certain components of a symbol
- to implement the semantics of variables. See symbol-value and symbol-function.
- However, there are several possible implementation strategies, and so such
- possible components are not described here.
-
- -------------------------------------------------------------------------------
-
- * The Property List
- * The Print Name
- * Creating Symbols
-
- -------------------------------------------------------------------------------
-
- 10.1. The Property List
-
- Since its inception, Lisp has associated with each symbol a kind of tabular
- data structure called a property list (plist for short). A property list
- contains zero or more entries; each entry associates with a key (called the
- indicator), which is typically a symbol, an arbitrary Lisp object (called the
- value or, sometimes, the property). There are no duplications among the
- indicators; a property list may only have one property at a time with a given
- name. In this way, given a symbol and an indicator (another symbol), an
- associated value can be retrieved.
-
- A property list is very similar in purpose to an association list. The
- difference is that a property list is an object with a unique identity; the
- operations for adding and removing property-list entries are destructive
- operations that alter the property list rather than making a new one.
- Association lists, on the other hand, are normally augmented non-destructively
- (without side effects) by adding new entries to the front (see acons and
- pairlis).
-
- A property list is implemented as a memory cell containing a list with an even
- number (possibly zero) of elements. (Usually this memory cell is the
- property-list cell of a symbol, but any memory cell acceptable to setf can be
- used if getf and remf are used.) Each pair of elements in the list constitutes
- an entry; the first item is the indicator, and the second is the value. Because
- property-list functions are given the symbol and not the list itself,
- modifications to the property list can be recorded by storing back into the
- property-list cell of the symbol.
-
- When a symbol is created, its property list is initially empty. Properties are
- created by using get within a setf form.
-
- Common Lisp does not use a symbol's property list as extensively as earlier
- Lisp implementations did. Less-used data, such as compiler, debugging, and
- documentation information, is kept on property lists in Common Lisp.
-
- -------------------------------------------------------------------------------
- Compatibility note: In older Lisp implementations, the print name, value, and
- function definition of a symbol were kept on its property list. The value cell
- was introduced into MacLisp and Interlisp to speed up access to variables;
- similarly for the print-name cell and function cell (MacLisp does not use a
- function cell). Recent Lisp implementations such as Spice Lisp, Lisp Machine
- Lisp, and NIL have introduced all of these cells plus the package cell. None of
- the MacLisp system property names (expr, fexpr, macro, array, subr, lsubr,
- fsubr, and in former times value and pname) exist in Common Lisp.
-
- In Common Lisp, the notion of ``disembodied property list'' introduced in
- MacLisp is eliminated. It tended to be used for rather kludgy things, and in
- Lisp Machine Lisp is often associated with the use of locatives (to make it
- ``off by one'' for searching alternating keyword lists). In Common Lisp special
- setf-like property-list functions are introduced: getf and remf.
- -------------------------------------------------------------------------------
-
- [Function]
- get symbol indicator &optional default
-
- get searches the property list of symbol for an indicator eq to indicator. The
- first argument must be a symbol. If one is found, then the corresponding value
- is returned; otherwise default is returned.
-
- If default is not specified, then nil is used for default.
-
- Note that there is no way to distinguish an absent property from one whose
- value is default.
-
- (get x y) == (getf (symbol-plist x) y)
-
- Suppose that the property list of foo is (bar t baz 3 hunoz "Huh?"). Then, for
- example:
-
- (get 'foo 'baz) => 3
- (get 'foo 'hunoz) => "Huh?"
- (get 'foo 'zoo) => nil
-
- -------------------------------------------------------------------------------
- Compatibility note: In MacLisp, the first argument to get could be a list, in
- which case the cdr of the list was treated as a so-called ``disembodied
- property list.'' The first argument to get could also be any other object, in
- which case get would always return nil. In Common Lisp, it is an error to give
- anything but a symbol as the first argument to get.
-
- What Common Lisp calls get, Interlisp calls getprop.
-
- What MacLisp and Interlisp call putprop is accomplished in Common Lisp by using
- get with setf.
- -------------------------------------------------------------------------------
-
- setf may be used with get to create a new property-value pair, possibly
- replacing an old pair with the same property name. For example:
-
- (get 'clyde 'species) => nil
- (setf (get 'clyde 'species) 'elephant) => elephant
- and now (get 'clyde 'species) => elephant
-
- The default argument may be specified to get in this context; it is ignored by
- setf but may be useful in such macros as push that are related to setf:
-
- (push item (get sym 'token-stack '(initial-item)))
-
- means approximately the same as
-
- (setf (get sym 'token-stack '(initial-item))
- (cons item (get sym 'token-stack '(initial-item))))
-
- which in turn would be treated as simply
-
- (setf (get sym 'token-stack)
- (cons item (get sym 'token-stack '(initial-item))))
-
- [change_begin]
- X3J13 voted in March 1989 (REMF-DESTRUCTION-UNSPECIFIED) to clarify the
- permissible side effects of certain operations; (setf (get symbol indicator)
- newvalue) is required to behave exactly the same as (setf (getf (symbol-plist
- symbol) indicator) newvalue).
- [change_end]
-
- [Function]
- remprop symbol indicator
-
- This removes from symbol the property with an indicator eq to indicator. The
- property indicator and the corresponding value are removed by destructively
- splicing the property list. It returns nil if no such property was found, or
- non-nil if a property was found.
-
- (remprop x y) == (remf (symbol-plist x) y)
-
- For example, if the property list of foo is initially
-
- (color blue height 6.3 near-to bar)
-
- then the call
-
- (remprop 'foo 'height)
-
- returns a non-nil value after altering foo's property list to be
-
- (color blue near-to bar)
-
- [change_begin]
- X3J13 voted in March 1989 (REMF-DESTRUCTION-UNSPECIFIED) to clarify the
- permissible side effects of certain operations; (remprop symbol indicator) is
- required to behave exactly the same as (remf (symbol-plist symbol) indicator).
- [change_end]
-
- [Function]
- symbol-plist symbol
-
- This returns the list that contains the property pairs of symbol; the contents
- of the property-list cell are extracted and returned.
-
- Note that using get on the result of symbol-plist does not work. One must give
- the symbol itself to get or else use the function getf.
-
- setf may be used with symbol-plist to destructively replace the entire property
- list of a symbol. This is a relatively dangerous operation, as it may destroy
- important information that the implementation may happen to store in property
- lists. Also, care must be taken that the new property list is in fact a list of
- even length.
-
- -------------------------------------------------------------------------------
- Compatibility note: In MacLisp, this function is called plist; in Interlisp, it
- is called getproplist.
- -------------------------------------------------------------------------------
-
- [Function]
- getf place indicator &optional default
-
- getf searches the property list stored in place for an indicator eq to
- indicator. If one is found, then the corresponding value is returned; otherwise
- default is returned. If default is not specified, then nil is used for default.
- Note that there is no way to distinguish an absent property from one whose
- value is default. Often place is computed from a generalized variable
- acceptable to setf.
-
- setf may be used with getf, in which case the place must indeed be acceptable
- as a place to setf. The effect is to add a new property-value pair, or update
- an existing pair, in the property list kept in the place. The default argument
- may be specified to getf in this context; it is ignored by setf but may be
- useful in such macros as push that are related to setf. See the description of
- get for an example of this.
-
- [change_begin]
- X3J13 voted in March 1989 (REMF-DESTRUCTION-UNSPECIFIED) to clarify the
- permissible side effects of certain operations; setf used with getf is
- permitted to perform a setf on the place or on any part, car or cdr, of the
- top-level list structure held by that place.
-
- X3J13 voted in March 1988 (PUSH-EVALUATION-ORDER) to clarify order of
- evaluation (see section 7.2).
- [change_end]
-
- -------------------------------------------------------------------------------
- Compatibility note: The Interlisp function listget is similar to getf. The
- Interlisp function listput is similar to using getf with setf.
- -------------------------------------------------------------------------------
-
- [Macro]
- remf place indicator
-
- This removes from the property list stored in place the property with an
- indicator eq to indicator. The property indicator and the corresponding value
- are removed by destructively splicing the property list. remf returns nil if no
- such property was found, or some non-nil value if a property was found. The
- form place may be any generalized variable acceptable to setf. See remprop.
-
- [change_begin]
- X3J13 voted in March 1989 (REMF-DESTRUCTION-UNSPECIFIED) to clarify the
- permissible side effects of certain operations; remf is permitted to perform a
- setf on the place or on any part, car or cdr, of the top-level list structure
- held by that place.
-
- X3J13 voted in March 1988 (PUSH-EVALUATION-ORDER) to clarify order of
- evaluation (see section 7.2).
- [change_end]
-
- [Function]
- get-properties place indicator-list
-
- get-properties is like getf, except that the second argument is a list of
- indicators. get-properties searches the property list stored in place for any
- of the indicators in indicator-list until it finds the first property in the
- property list whose indicator is one of the elements of indicator-list.
- Normally place is computed from a generalized variable acceptable to setf.
-
- get-properties returns three values. If any property was found, then the first
- two values are the indicator and value for the first property whose indicator
- was in indicator-list, and the third is that tail of the property list whose
- car was the indicator (and whose cadr is therefore the value). If no property
- was found, all three values are nil. Thus the third value serves as a flag
- indicating success or failure and also allows the search to be restarted, if
- desired, after the property was found.
-
- -------------------------------------------------------------------------------
-
- 10.2. The Print Name
-
- Every symbol has an associated string called the print name. This string is
- used as the external representation of the symbol: if the characters in the
- string are typed in to read (with suitable escape conventions for certain
- characters), it is interpreted as a reference to that symbol (if it is
- interned); and if the symbol is printed, print types out the print name. For
- more information, see the sections on the reader (section 22.1.1) and printer
- (section 22.1.6).
-
- [Function]
- symbol-name sym
-
- This returns the print name of the symbol sym. For example:
-
- (symbol-name 'xyz) => "XYZ"
-
- It is an extremely bad idea to modify a string being used as the print name of
- a symbol. Such a modification may tremendously confuse the function read and
- the package system.
-
- [change_begin]
- X3J13 voted in March 1989 (CHARACTER-PROPOSAL) to specify that it is an error
- to modify a string being used as the print name of a symbol.
- [change_end]
-
- -------------------------------------------------------------------------------
-
- 10.3. Creating Symbols
-
- Symbols can be used in two rather different ways. An interned symbol is one
- that is indexed by its print name in a catalogue called a package. A request to
- locate a symbol with that print name results in the same (eq) symbol. Every
- time input is read with the function read, and that print name appears, it is
- read as the same symbol. This property of symbols makes them appropriate to use
- as names for things and as hooks on which to hang permanent data objects (using
- the property list, for example).
-
- Interned symbols are normally created automatically; the first time something
- (such as the function read) asks the package system for a symbol with a given
- print name, that symbol is automatically created. The function used to ask for
- an interned symbol is intern, or one of the functions related to intern.
-
- Although interned symbols are the most commonly used, they will not be
- discussed further here. For more information, see chapter 11.
-
- An uninterned symbol is a symbol used simply as a data object, with no special
- cataloguing (it belongs to no particular package). An uninterned symbol is
- printed as #: followed by its print name. The following are some functions for
- creating uninterned symbols.
-
- [Function]
- make-symbol print-name
-
- (make-symbol print-name) creates a new uninterned symbol, whose print name is
- the string print-name. The value and function bindings will be unbound and the
- property list will be empty.
-
- The string actually installed in the symbol's print-name component may be the
- given string print-name or may be a copy of it, at the implementation's
- discretion. The user should not assume that (symbol-name (make-symbol x)) is eq
- to x, but also should not alter a string once it has been given as an argument
- to make-symbol.
-
- -------------------------------------------------------------------------------
- Compatibility note: An implementation might choose, for example, to copy the
- string to some read-only area, in the expectation that it will never be
- altered.
- -------------------------------------------------------------------------------
-
- [Function]
- copy-symbol sym &optional copy-props
-
- This returns a new uninterned symbol with the same print name as sym.
-
- [change_begin]
- X3J13 voted in March 1989 (COPY-SYMBOL-PRINT-NAME) that the print name of the
- new symbol is required to be the same only in the sense of string=; in other
- words, an implementation is permitted (but not required) to make a copy of the
- print name. User programs should not assume that the print names of the old and
- new symbols will be eq, although they may happen to be eq in some
- implementations.
- [change_end]
-
- If copy-props is non-nil, then the initial value and function definition of the
- new symbol will be the same as those of sym, and the property list of the new
- symbol will be a copy of sym's.
-
- [change_begin]
- X3J13 voted in March 1989 (COPY-SYMBOL-COPY-PLIST) to clarify that only the
- top-level conses of the property list are copied; it is as if (copy-list
- (symbol-plist sym)) were used as the property list of the new symbol.
- [change_end]
-
- If copy-props is nil (the default), then the new symbol will be unbound and
- undefined, and its property list will be empty.
-
- [Function]
- gensym &optional x
-
- gensym invents a print name and creates a new symbol with that print name. It
- returns the new, uninterned symbol.
-
- The invented print name consists of a prefix (which defaults to G), followed by
- the decimal representation of a number.
-
- [old_change_begin]
- The number is increased by 1 every time gensym is called.
-
- If the argument x is present and is an integer, then x must be non-negative,
- and the internal counter is set to x for future use; otherwise the internal
- counter is incremented. If x is a string, then that string is made the default
- prefix for this and future calls to gensym. After handling the argument, gensym
- creates a symbol as it would with no argument. For example:
-
- (gensym) => G7
- (gensym "FOO-") => FOO-8
- (gensym 32) => FOO-32
- (gensym) => FOO-33
- (gensym "GARBAGE-") => GARBAGE-34
-
- [old_change_end]
-
- gensym is usually used to create a symbol that should not normally be seen by
- the user and whose print name is unimportant except to allow easy distinction
- by eye between two such symbols. The optional argument is rarely supplied. The
- name comes from ``generate symbol,'' and the symbols produced by it are often
- called ``gensyms.''
-
- -------------------------------------------------------------------------------
- Compatibility note: In earlier versions of Lisp, such as MacLisp and Interlisp,
- the print name of a gensym was of fixed length, consisting of a single letter
- and a fixed-length decimal representation with leading zeros if necessary, for
- example, G0007. This convention was motivated by an implementation
- consideration, namely that the name should fit into a single machine word,
- allowing a quick and clever implementation. Such considerations are less
- relevant in Common Lisp. The consistent use of mnemonic prefixes can make it
- easier for the programmer, when debugging, to determine what code generated a
- particular symbol. The elimination of the fixed-length decimal representation
- prevents the same name from being used twice unless the counter is explicitly
- reset.
- -------------------------------------------------------------------------------
-
- If it is desirable for the generated symbols to be interned, and yet guaranteed
- to be symbols distinct from all others, then the function gentemp may be more
- appropriate to use.
-
- [change_begin]
- X3J13 voted in March 1989 (GENSYM-NAME-STICKINESS) to alter the specification
- of gensym so that supplying an optional argument (whether a string or a number)
- does not alter the internal state maintained by gensym. Instead, the internal
- counter is made explicitly available as a variable named *gensym-counter*.
-
- If a string argument is given to gensym, that string is used as the prefix;
- otherwise ``G'' is used. If a number is provided, its decimal representation is
- used, but the internal counter is unaffected. X3J13 deprecates the use of a
- number as an argument.
-
- [Variable]
- *gensym-counter*
-
- X3J13 voted in March 1989 (GENSYM-NAME-STICKINESS) to add *gensym-counter*,
- which holds the state of the gensym counter; that is, gensym uses the decimal
- representation of its value as part of the generated name and then increments
- its value.
-
- The initial value of this variable is implementation-dependent but will be a
- non-negative integer.
-
- The user may assign to or bind this variable at any time, but its value must
- always be a non-negative integer.
- [change_end]
-
- [Function]
- gentemp &optional prefix package
-
- gentemp, like gensym, creates and returns a new symbol. gentemp differs from
- gensym in that it interns the symbol (see intern) in the package (which
- defaults to the current package; see *package*). gentemp guarantees the symbol
- will be a new one not already existing in the package. It does this by using a
- counter as gensym does, but if the generated symbol is not really new, then the
- process is repeated until a new one is created. There is no provision for
- resetting the gentemp counter. Also, the prefix for gentemp is not remembered
- from one call to the next; if prefix is omitted, the default prefix T is used.
-
- [Function]
- symbol-package sym
-
- Given a symbol sym, symbol-package returns the contents of the package cell of
- that symbol. This will be a package object or nil.
-
- [Function]
- keywordp object
-
- The argument may be any Lisp object. The predicate keywordp is true if the
- argument is a symbol and that symbol is a keyword (that is, belongs to the
- keyword package). Keywords are those symbols that are written with a leading
- colon. Every keyword is a constant, in the sense that it always evaluates to
- itself. See constantp.
-
- -------------------------------------------------------------------------------
-
-
-
-
-